//
//  NSFileInfoItem.m
//  Penda
//
//  Created by Duckjin Kang on 1/4/10.
//  Copyright 2010 StonyBrookUniv.. All rights reserved.
//

#import "NSFileInfoItem.h"
#include <sys/stat.h>
#include <sys/time.h>

@implementation NSFileInfoItem

@synthesize attributes, name, dirtyAccess, dirtyModify, dirtyCreate, newName;
@synthesize fileTitle, fileExt, parentPath, fileName;

#define SET_OBSERVER(path)		\
	[self addObserver:self forKeyPath:path\
	options:NSKeyValueObservingOptionNew context:nil];
#define CLR_OBSERVER(path)		\
	[self removeObserver:self forKeyPath:path];

- (BOOL)isEqual:(id)anObject {
	if ([[anObject class] isEqual:[self class]]) {
		return [self.name isEqual:[anObject name] ];
	}
	return NO;
}

-(BOOL) flush {
	NSFileManager* fm = [NSFileManager defaultManager];
	if (self.dirtyCreate | self.dirtyModify) {
		NSDictionary *pAttr = [NSDictionary 
							   dictionaryWithObjects:
								[NSArray arrayWithObjects:
								 [[self.attributes objectForKey:@"NSFileCreationDate"] copy],
								 [[self.attributes objectForKey:@"NSFileModificationDate"] copy],
								 nil
								 ]
							   forKeys:
								[NSArray arrayWithObjects:
								 @"NSFileCreationDate",
								 @"NSFileModificationDate",
								 nil
								 ]
							   ];
		if ([fm setAttributes:pAttr ofItemAtPath:self.name error:nil]) {
			self.dirtyCreate = NO;
			self.dirtyModify = NO;
		} else 
			goto error;
	}
	// access time can be updated with utimes system call
	if (self.dirtyAccess) {
		struct timeval times[2] = {
			{[ [attributes objectForKey:@"NSFileAccessDate"] timeIntervalSince1970] ,0},
			{[ [attributes objectForKey:@"NSFileModificationDate"] timeIntervalSince1970] ,0},
		};
		int ret = utimes([name UTF8String], times);
		if (ret==0) {
			self.dirtyAccess = NO;
		} else 
			goto error;
	}
	// filename
	if (newName && [newName length]) {
		NSString *newPath = [NSString stringWithFormat:@"%@/%@",[self parentPath], newName];
		if ([fm moveItemAtPath:name toPath:newPath error:nil]) {
			self.name = newPath;
		} else {
			goto error;
		}

	}
	return YES;
error:
	return NO;
}

-(NSMutableDictionary*) attributes {
	if (attributes == nil) {
		attributes = [[NSMutableDictionary alloc] init];
	}
	return attributes;
}

-(NSFileInfoItem*) initWithFilePath:(NSString*) path {
	[super init];
	self.name = path;
	SET_OBSERVER(@"attributes.NSFileAccessDate");
	SET_OBSERVER(@"attributes.NSFileCreationDate");
	SET_OBSERVER(@"attributes.NSFileModificationDate");
	return self;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
	if ([keyPath isEqual:@"attributes.NSFileAccessDate"]) {
		NSLog(@"%@",[attributes objectForKey:@"NSFileAccessDate"]);
		self.dirtyAccess = YES;
	} else if ([keyPath isEqual:@"attributes.NSFileCreationDate"]) {
		NSLog(@"%@",[attributes objectForKey:@"NSFileCreationDate"]);
		self.dirtyCreate = YES;
	} else if ([keyPath isEqual:@"attributes.NSFileModificationDate"]) {
		NSLog(@"%@",[attributes objectForKey:@"NSFileModificationDate"]);
		self.dirtyModify = YES;
	}
}

- (void) setName:(NSString *)filePath {
	name = [filePath copy];
	self.fileName = [name lastPathComponent];
	self.fileTitle = [[name stringByDeletingPathExtension] lastPathComponent];
	self.fileExt = [name pathExtension];
	self.parentPath = [name stringByDeletingLastPathComponent];
	
	NSFileManager* fm = [NSFileManager defaultManager];
	NSDictionary* gotAttributes = [fm attributesOfItemAtPath:name error:nil];
	[self.attributes removeAllObjects];
	[self.attributes addEntriesFromDictionary:gotAttributes];
	// Access time
	struct stat data;
	if (stat([name UTF8String], &data) == 0 ) {
		NSDate *pDate = [NSDate dateWithTimeIntervalSince1970:data.st_atime];
		[attributes setObject:pDate forKey:@"NSFileAccessDate"];
	}
	// kind string
    CFStringRef kindStr = nil;
    LSCopyKindStringForURL((CFURLRef)[NSURL fileURLWithPath:name], &kindStr);
    if (kindStr !=  nil)
    {
		[attributes setObject:(NSString*)kindStr forKey:@"NSKindString"];
        CFRelease(kindStr);
    }
}

- (void) setDirtyCreate:(BOOL)dirty {
	dirtyCreate = dirty;
	if (!dirty) {
		NSFileManager* fm = [NSFileManager defaultManager];
		NSDictionary* newAttr = [NSMutableDictionary dictionaryWithDictionary:[fm attributesOfItemAtPath:name error:nil]];
		/* restore to original state */
		CLR_OBSERVER(@"attributes.NSFileCreationDate");
		[attributes setObject:[newAttr objectForKey:@"NSFileCreationDate"] forKey:@"NSFileCreationDate"];
		SET_OBSERVER(@"attributes.NSFileCreationDate");
	}
}
- (void) setDirtyAccess:(BOOL)dirty {
	dirtyAccess = dirty;
	if (!dirty) {
		/* Access time */
		struct stat data;
		if (stat([name UTF8String], &data) == 0 ) {
			NSDate *pDate = [NSDate dateWithTimeIntervalSince1970:data.st_atime];
			CLR_OBSERVER(@"attributes.NSFileAccessDate");
			[attributes setObject:pDate forKey:@"NSFileAccessDate"];
			SET_OBSERVER(@"attributes.NSFileAccessDate");
		}
	}
}
- (void) setDirtyModify:(BOOL)dirty {
	dirtyModify = dirty;
	if (!dirty) {
		NSFileManager* fm = [NSFileManager defaultManager];
		NSDictionary* newAttr = [NSMutableDictionary dictionaryWithDictionary:[fm attributesOfItemAtPath:name error:nil]];
		/* restore to original state */
		CLR_OBSERVER(@"attributes.NSFileModificationDate");
		[attributes setObject:[newAttr objectForKey:@"NSFileModificationDate"] forKey:@"NSFileModificationDate"];
		SET_OBSERVER(@"attributes.NSFileModificationDate");
	}
}

- (void) dealloc {
	CLR_OBSERVER(@"attributes.NSFileAccessDate");
	CLR_OBSERVER(@"attributes.NSFileCreationDate");
	CLR_OBSERVER(@"attributes.NSFileModificationDate");
	[attributes release];
	[super dealloc];
}
@end
